(function() {
    this.Browser.Features.websockets = ("WebSocket" in window);

    WebSocket.extend = function(key, value) {
        this[key] = value;
    }.overloadSetter();

    var prototype = WebSocket.prototype;
    var websocket = new Type("WebSocket", WebSocket);

    var send = prototype.send;
    delete prototype.send;
    prototype.send = send.protect();

    var close = prototype.close;
    delete prototype.close;
    prototype.close = close.protect();

    websocket.implement(prototype);

    var eventlist = {};
    /* Inspired by mootools Element.Event */
    WebSocket.implement({
        addEvent: function(type, fn) {
            var self = this;
            if(!eventlist[type]) eventlist[type] = {
                keys: [],
                values: []
            };
            if(eventlist[type].keys.contains(fn)) return this;
            eventlist[type].keys.push(fn);
            var defn = function(event) {
                return fn.call(self, event);
            }
            if(this.addEventListener) this.addEventListener(type, defn, !!arguments[2]);
            else this.attachEvent("on" + type, defn);
            eventlist[type].values.push(defn);
            return this;
        },
        removeEvent: function(type, fn) {
            if(!eventlist[type]) return this;
            var list = eventlist[type];
            var index = list.keys.indexOf(fn);
            if(index == -1) return this;
            var value = list.values[index];
            delete list.keys[index];
            delete list.values[index];
            if(this.removeEventListener) this.removeEventListener(type, value, !!arguments[2]);
            else this.detachEvent("on" + type, value);
            return this;
        },
        addEvents: function(events) {
            for (var event in events) this.addEvent(event, events[event]);
            return this;
        },
        removeEvents: function(events) {
            var type;
            if(typeOf(events) == "object") {
                for(type in events) this.removeEvent(type, events[type]);
                return this;
            }
            if(!events) {
                for(type in eventlist) this.removeEvents(type);
            } else if(eventlist[events]) {
                eventlist[events].keys.each(function(fn) {
                    this.remoreEvent(events, fn);
                }, this);
                delete eventlist[event];
            }
            return this;
        },
        getReadyState: function() {
            switch(this.readyState) {
                case this.CONNECTING:
                    return "connecting";
                    break;
                case this.OPEN:
                    return "open";
                    break;
                case this.CLOSING:
                    return "closing";
                    break;
                case this.CLOSED:
                    return "closed";
                    break;
            }
        }
    });
})();